package cn.momoky.ccool.service;

import cn.momoky.ccool.exception.GlobalException;
import cn.momoky.ccool.pojo.Chunk;
import cn.momoky.ccool.pojo.UploadTask;
import cn.momoky.ccool.utils.ResultStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class FileService {

    @Value("${upload.path}")
    String path;

    private final FileMD5Service fileMD5Service;

    public FileService(FileMD5Service fileMD5Service) {
        this.fileMD5Service = fileMD5Service;
    }

    public boolean uploadChunk(Chunk chunk) {
        MultipartFile file = chunk.getFile();

        File dest = new File(path + "/" + chunk.getTaskId() + "/" + chunk.getSeq());
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }

        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return true;
    }

    public void mergeChunk(UploadTask uploadTask) {
        Long nodeId = uploadTask.getId();
        File file = new File(path + "/" + uploadTask.getMd5());

        try {
            FileOutputStream out = new FileOutputStream(file);

            int ret = 0;
            byte[] buf = new byte[4096];

            for (int i = 0; i < uploadTask.getChunkCount(); i++) {
                File chunkFile = new File(path + "/" + nodeId + "/" + i);
                FileInputStream in = new FileInputStream(chunkFile);
                while ((ret = in.read(buf)) > 0) {
                    out.write(buf, 0, ret);
                }
                in.close();
                chunkFile.delete();
            }

            out.close();
            new File(path + "/" + nodeId).delete();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void del(List<String> md5s) {
        md5s.forEach(md5 -> {
            new File(path + "/" +md5).delete();
        });
    }

    public void del(String md5) {
        List<String> md5List = new ArrayList<>();
        md5List.add(md5);
        del(md5List);
    }

    public void download(String md5, HttpServletResponse resp) throws IOException {
        FileInputStream in = new FileInputStream(path + "/" + md5);
        ServletOutputStream out = resp.getOutputStream();
        byte[] buf = new byte[4096];
        int ret = 0;
        while ((ret = in.read(buf)) > 0) {
            out.write(buf, 0, ret);
        }
        in.close();
        out.close();
    }

    public FileInputStream getFileInputStream(Long id) {
        String md5 = fileMD5Service.getMD5ByNodeId(id);

        if (md5 == null || md5.length() <= 0) {
            log.info(id + " 文件未找到");
            throw new GlobalException(ResultStatus.NOT_FOUND.getCode(), ResultStatus.NOT_FOUND.getMsg());
        }

        FileInputStream in = null;
        try {
            in = new FileInputStream(path + "/" + md5);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        return in;
    }
}
